package com.xxg.renrenorder.strategy;

import com.xxg.renrencommon.domain.filedenum.orderenum.OrderStatusEnum;
import com.xxg.renrencommon.exception.OrderManagerException;
import com.xxg.renrencommon.exception.exceptionenum.OrderExceptionCodeCodeEnum;
import com.xxg.renrenorder.dao.AfterSalesOrderInfoDao;
import com.xxg.renrenorder.dao.bean.AfterSalesOrderInfo;
import com.xxg.renrenorder.dao.bean.AfterSalesStep;
import com.xxg.renrenorder.dao.bean.OrderMasterInfo;
import com.xxg.renrenorder.dao.bean.ProductInfo;
import lombok.Data;

import java.math.BigDecimal;
import java.util.*;

/**
 * 类说明
 *
 * @author szj
 * @date 2021/12/17
 */
@Data
public abstract class AbstractAfterSalesStrategy implements AfterSalesStrategy{
    private Boolean returnProduct = false;
    private AfterSalesOrderInfoDao afterSalesOrderInfoDao;
    protected final static Long FIFTEEN_DAYS = 1296000000L;
    protected final static Long THIRTY_DAYS = 2592000000L;
    protected final static Long YEAR = 31536000000L;
    private final static HashMap<Integer, HashMap<Integer, HashSet<Integer>>> orderStatusTypeReason;

    static {
        orderStatusTypeReason = initStatusTypeReason();
    }

    /**
     * 初始化订单状态下支持的售后类型和对应的原因
     *
     * @return 结果
     */
    private static HashMap<Integer, HashMap<Integer, HashSet<Integer>>> initStatusTypeReason() {
        HashMap<Integer, HashMap<Integer, HashSet<Integer>>> map = new HashMap<>();
        // --待发货
        HashMap<Integer, HashSet<Integer>> statusType = new HashMap<>();
        map.put(OrderStatusEnum.UN_EXPRESS.getValue(), statusType);
        // 仅退款
        statusType.put(1, new HashSet<>(Arrays.asList(4, 5)));
        // --待收货
        statusType = new HashMap<>();
        map.put(OrderStatusEnum.UN_COMMIT.getValue(), statusType);
        // 仅退款
        statusType.put(1, new HashSet<>(Arrays.asList(6, 7)));
        // 退货退款
        statusType.put(3, new HashSet<>(Arrays.asList(1, 2, 3, 4, 5)));
        // 维修
        statusType.put(4, new HashSet<>(Arrays.asList(4, 9)));
        // 换货
        statusType.put(5, new HashSet<>(Arrays.asList(4, 9)));
        // 补寄
        statusType.put(6, new HashSet<>(Arrays.asList(4, 8)));
        // 补寄配件
        statusType.put(7, new HashSet<>(Arrays.asList(4, 9)));
        // --已完成15天内
        statusType = new HashMap<>();
        map.put(15, statusType);
        // 仅退款
        statusType.put(1, new HashSet<>(Collections.singletonList(6)));
        // 退货退款
        statusType.put(3, new HashSet<>(Arrays.asList(1, 2, 3, 4, 5)));
        // --已完成30天内
        statusType = new HashMap<>();
        map.put(30, statusType);
        // 补寄配件
        statusType.put(7, new HashSet<>(Arrays.asList(4, 9)));
        // 换货
        statusType.put(5, new HashSet<>(Arrays.asList(4, 9)));
        // --已完成1年内
        statusType = new HashMap<>();
        map.put(365, statusType);
        // 维修
        statusType.put(4, new HashSet<>(Arrays.asList(4, 9)));
        return map;
    }

    protected String getOrderStatusName(Integer orderStatus) {
        // 检查售后原因是否匹配
        OrderStatusEnum statusEnum = OrderStatusEnum.class.getEnumConstants()[orderStatus - 1];
        return statusEnum.getName();
    }

    protected String getReason(AfterSalesOrderInfo afterSalesOrderInfo) {
        String reason = "原因：";
        switch (afterSalesOrderInfo.getReasonType()) {
            case 1:
                // 损坏
                reason += "损坏";
                break;
            case 2:
                // 质量问题
                reason += "质量问题";
                break;
            case 3:
                // 发错货
                reason += "发错货";
                break;
            case 4:
                // 其他
                reason += "其他";
                break;
            case 5:
                // 不喜欢/不合适
                reason += "不喜欢/不合适";
                break;
            case 6:
                // 协商退款
                reason += "协商退款";
                break;
            case 7:
                // 未收到货
                reason += "未收到货";
                break;
            case 8:
                // 缺件
                reason += "缺件";
                break;
            case 9:
                // 商品故障
                reason += "商品故障";
                break;
            default:
                reason += "未知";
                break;
        }
        if (afterSalesOrderInfo.getNumber() != null) {
            reason += "；申请件数：" + afterSalesOrderInfo.getNumber();
        }
        if (afterSalesOrderInfo.getApplyReturnPay() != null) {
            reason += "；申请金额：" + afterSalesOrderInfo.getApplyReturnPay().toString();
        }
        return reason;
    }

    /**
     * 检查是否超过规定期限
     *
     * @param now             当前时间
     * @param orderMasterInfo 订单信息
     * @param days            期限
     * @throws OrderManagerException 异常信息
     */
    protected void checkExpired(Date now, OrderMasterInfo orderMasterInfo, long days) throws OrderManagerException {
        if (orderMasterInfo.getOrderStatus() == OrderStatusEnum.SUCCESS.getValue()) {
            long doneTime = orderMasterInfo.getDoneTime().getTime();
            long nowTime = now.getTime();
            // 已完成超过设定天数，不受理
            if (nowTime - doneTime > days) {
                throw new OrderManagerException(OrderExceptionCodeCodeEnum.ORDER_EXPIRE_DAYS);
            }
        }
    }

    /**
     * 查询是否处理过其他的售后申请
     *
     * @param orderMasterInfo     订单信息
     * @param afterSalesOrderInfo 售后订单信息
     * @throws OrderManagerException 异常信息
     */
    protected void hasDoneOtherAfterSales(OrderMasterInfo orderMasterInfo, AfterSalesOrderInfo afterSalesOrderInfo) throws OrderManagerException {
        if (afterSalesOrderInfoDao.hasDoneOtherAfterSales(orderMasterInfo.getId(), afterSalesOrderInfo.getProductInfo().getSkuId())) {
            throw new OrderManagerException(OrderExceptionCodeCodeEnum.HAS_OTHER_AFTER_SALES);
        }
    }

    /**
     * 检查是否之前就处理过仅退款的售后
     *
     * @param orderMasterInfo     订单信息
     * @param afterSalesOrderInfo 售后订单信息
     * @throws OrderManagerException 异常信息
     */
    protected void hasDoneBefore(OrderMasterInfo orderMasterInfo, AfterSalesOrderInfo afterSalesOrderInfo) throws OrderManagerException {
        if (afterSalesOrderInfoDao.hasDoneBeforeOrderByType(orderMasterInfo.getId(), afterSalesOrderInfo.getProductInfo().getSkuId())) {
            throw new OrderManagerException(OrderExceptionCodeCodeEnum.ONLY_ONCE);
        }
    }

    /**
     * 检验申请金额和设置退款金额
     *
     * @param afterSalesOrderInfo 售后申请
     * @param maxNumber           最大可退的商品数量
     * @throws OrderManagerException 异常信息
     */
    protected void checkAndSetReturnPay(AfterSalesOrderInfo afterSalesOrderInfo, int maxNumber) throws OrderManagerException {
        if (afterSalesOrderInfo.getApplyReturnPay() == null) {
            throw new OrderManagerException(OrderExceptionCodeCodeEnum.APPLY_RETURN_PAY_CANNOT_NULL);
        } else {
            // 最大可申请金额
            BigDecimal maxReturnPay = afterSalesOrderInfo.getProductInfo().getSkuPrice().multiply(new BigDecimal(maxNumber));
            if (afterSalesOrderInfo.getApplyReturnPay().compareTo(maxReturnPay) <= 0) {
                afterSalesOrderInfo.setReturnPay(afterSalesOrderInfo.getApplyReturnPay());
            } else {
                throw new OrderManagerException(OrderExceptionCodeCodeEnum.APPLY_RETURN_PAY_TOO_MUCH);
            }
        }
    }

    /**
     * 查询当前售后类型是否被永久拒绝
     *
     * @param orderMasterInfo     订单信息
     * @param afterSalesOrderInfo 售后订单信息
     * @throws OrderManagerException 异常信息
     */
    protected void hasForeverRejected(OrderMasterInfo orderMasterInfo, AfterSalesOrderInfo afterSalesOrderInfo) throws OrderManagerException {
        if (afterSalesOrderInfoDao.hasForeverRejectedOrderByType(orderMasterInfo.getId(), afterSalesOrderInfo.getAfterSalesType(), afterSalesOrderInfo.getProductInfo().getSkuId())) {
            throw new OrderManagerException(OrderExceptionCodeCodeEnum.FOREVER_REJECTED);
        }
    }

    /**
     * 查询是否有正在进行的售后订单
     *
     * @param orderMasterInfo     订单信息
     * @param afterSalesOrderInfo 售后订单信息
     * @throws OrderManagerException 异常信息
     */
    protected void hasUnFinishAfterSalesOrder(OrderMasterInfo orderMasterInfo, AfterSalesOrderInfo afterSalesOrderInfo) throws OrderManagerException {
        long count = afterSalesOrderInfoDao.getUnFinishOrderCountByOrderId(orderMasterInfo.getId(), afterSalesOrderInfo.getProductInfo().getSkuId());
        if (count > 0) {
            throw new OrderManagerException(OrderExceptionCodeCodeEnum.HAS_UNFINISHED_AS_ORDERS);
        }
    }

    /**
     * 检查申请的数量是否合法
     *
     * @param orderMasterInfo     订单信息
     * @param afterSalesOrderInfo 售后订单信息
     * @return 可退的最大数量
     * @throws OrderManagerException 异常信息
     */
    protected int checkApplyNumber(OrderMasterInfo orderMasterInfo, AfterSalesOrderInfo afterSalesOrderInfo) throws OrderManagerException {
        int maxNumber;
        ProductInfo product = null;
        for (ProductInfo productInfo : orderMasterInfo.getProductInfos()) {
            if (productInfo.getSkuId().equals(afterSalesOrderInfo.getProductInfo().getSkuId())) {
                product = productInfo;
                afterSalesOrderInfo.setProductInfo(productInfo);
                break;
            }
        }
        if (product == null) {
            throw new OrderManagerException(OrderExceptionCodeCodeEnum.SKU_NOT_EXISTS);
        }
        if (product.getReturnNumber() != null) {
            maxNumber = product.getNumber() - product.getReturnNumber();
        } else {
            maxNumber = product.getNumber();
        }
        // 申请售后数量不能超过有效数量
        if (maxNumber < afterSalesOrderInfo.getNumber()) {
            throw new OrderManagerException(OrderExceptionCodeCodeEnum.NUMBER_TOO_MANY);
        }
        return maxNumber;
    }

    /**
     * 检查售后申请的原因是否正确
     *
     * @param orderStatus 订单状态
     * @param salesType   售后类型
     * @param reason      售后原因
     * @param days        已完成的期限
     * @throws OrderManagerException 异常信息
     */
    protected void checkReason(Integer orderStatus, Integer salesType, Integer reason, Integer days) throws OrderManagerException {
        Integer statusKey = orderStatus;
        // 已完成并且在设定期限内
        if (orderStatus == OrderStatusEnum.SUCCESS.getValue() && days > 0) {
            statusKey = days;
        }
        if (orderStatusTypeReason.containsKey(statusKey)) {
            HashMap<Integer, HashSet<Integer>> typeReason = orderStatusTypeReason.get(statusKey);
            if (typeReason.containsKey(salesType)) {
                HashSet<Integer> reasonSet = typeReason.get(salesType);
                if (!reasonSet.contains(reason)) {
                    throw new OrderManagerException(OrderExceptionCodeCodeEnum.ORDER_STATUS_TYPE_REASON_NOT_MATCH);
                }
            }
        }
    }

    /**
     * 插入售后进度
     *
     * @param now                 当前时间
     * @param afterSalesOrderInfo 售后订单
     * @param description         进度描述
     * @param role                角色
     */
    public static void setStep(Date now, AfterSalesOrderInfo afterSalesOrderInfo, String description, Integer role) {
        AfterSalesStep afterSalesStep = new AfterSalesStep();
        afterSalesStep.setCreateTime(now);
        afterSalesStep.setDescription(description);
        afterSalesStep.setRole(role);
        if (afterSalesOrderInfo.getAfterSalesSteps() == null) {
            afterSalesOrderInfo.setAfterSalesSteps(Collections.singletonList(afterSalesStep));
        } else {
            afterSalesOrderInfo.getAfterSalesSteps().add(afterSalesStep);
        }
    }
}
